﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace TheKitchen.Client.ViewModels
{
    public class ValidationHandler
    {
        private Dictionary<string, List<BrokenRule>> BrokenRules { get; set; }

        public ValidationHandler()
        {
            BrokenRules = new Dictionary<string, List<BrokenRule>>();
        }

        public string this[string property]
        {
            get
            {
                if (BrokenRuleExistsFor(property))
                {
                    return string.Join(" ", GetBrokenRulesForProperty(property).Select(v => v.Message).ToArray());
                }
                else
                {
                    return null;
                }
            }
        }

        bool BrokenRuleExistsFor(string property)
        {
            return GetBrokenRulesForProperty(property).Count > 0;
        }

        public bool HasBrokenRules
        {
            get
            {
                return BrokenRules.Keys.Any(BrokenRuleExistsFor);
            }
        }

        public bool ValidateRule(string property, string ruleId, string message, Func<bool> ruleCheck)
        {
            if (!ruleCheck())
            {
                AddBrokenRule(property, ruleId, message);
                return false;
            } 
            else
            {
                RemoveBrokenRule(property, ruleId);
                return true;
            }
        }

        private void AddBrokenRule(string property, string ruleId, string message)
        {
            List<BrokenRule> brokenRules = GetBrokenRulesForProperty(property);

            if (!brokenRules.Any(r => r.Id == ruleId))
            {
                brokenRules.Add(new BrokenRule(ruleId, message));
            }
        }

        public void RemoveBrokenRule(string property, string ruleId)
        {
            List<BrokenRule> brokenRules = GetBrokenRulesForProperty(property);

            BrokenRule rule = brokenRules.SingleOrDefault(br => br.Id == ruleId);
            if (rule != null)
            {
                brokenRules.Remove(rule);
            }
        }

        private List<BrokenRule> GetBrokenRulesForProperty(string property)
        {
            if (!BrokenRules.ContainsKey(property))
            {
                BrokenRules[property] = new List<BrokenRule>();
            }

            return BrokenRules[property];
        }

        internal class BrokenRule
        {
            public BrokenRule(string ruleId, string message)
            {
                Id = ruleId;
                Message = message;
            }

            public string Id { get; set; }
            public string Message { get; set; }
        }
    }
}